package com.sxkiler.demo.rpc.server;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.sxkiler.demo.rpc.pojo.MessageContext;
import com.sxkiler.demo.rpc.pojo.Request;
import com.sxkiler.demo.rpc.pojo.Response;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;

import java.lang.reflect.Method;
import java.util.Map;
import java.util.Random;

public class NettyServerHandler extends ChannelInboundHandlerAdapter {
    // private NacosTemplate nacosTemplate;//集成nacos才用到，可以去掉

    private Map<String,Object> beans;

    public Map<String, Object> getBeans() {
        return beans;
    }

    public void setBeans(Map<String, Object> beans) {
        this.beans = beans;
    }

    public NettyServerHandler() {
        super();
        // nacosTemplate = new NacosTemplate();
    }

    @Override
    public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
        System.out.println("服务端 NioServerSocketChannel 已经和主eventLoopGroup中的某一个eventLoop绑定注册完成 Address ====== " + ctx.channel());
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        System.out.println("收到来自客户端的消息 ====== " + msg);
        if (msg instanceof MessageContext){
            channelRead0(ctx,(MessageContext) msg);
        }
    }

    //服务端主要调用逻辑在这里
    protected void channelRead0(ChannelHandlerContext channelHandlerContext, MessageContext messageContext) throws Exception {
        Object context = messageContext.getContext();
        Request request = JSON.parseObject(JSONObject.toJSONString(context), Request.class);//拿到消息体内的请求数据
        //将参数值和参数类型匹配对应
        Class<?>[] parameterType = request.getParameterType();
        Object[] parameterValue = request.getParameterValue();
        //由于参数值是通过json转换的，这边拿到的参数值全是JSONObject类型。所以需要将参数值按照参数类型重新转换一遍。
        if (parameterType.length == parameterValue.length){
            for (int i = 0; i < parameterValue.length; i++) {
                Object o = JSON.parseObject(JSONObject.toJSONString(parameterValue[i]), parameterType[i]);
                parameterValue[i] = o;
            }
        }
        System.out.println(context.getClass().getName());
        Object result = null ;
        Class<?> aClass = Class.forName(request.getClassName());
        //先判断bean容器是否为空，如果为空则可以拿到请求参数的类名（全限定名）反射去创建对象
        if (beans == null || beans.size() == 0) {//我这里逻辑没写，可以自己加(request.getClassName()传类的全限定名就可以)
            System.out.println("没有找到被调用的bean实例");
            channelHandlerContext.writeAndFlush(new MessageContext(String.valueOf(new Random().nextInt(9999)),false,new Response(true,new Object(),Object.class)));
            return;
        }
        Object o = beans.get(request.getServiceNameByAnnotated());
        //根据请求传的bean的name去bean容器里查，没查到则通过类全限定名反射创建对象
        if (o == null){
            System.out.println("beans里没找到实例，根据Class创建");
            o = aClass.newInstance();
        }
        Method method = aClass.getMethod(request.getMethodName(), request.getParameterType());
        Class<?> returnType = method.getReturnType();
        Object invoke = method.invoke(o, request.getParameterValue());
        if (returnType.isInstance(invoke)){//将调用结果转换为方法返回类型。
            result = returnType.cast(invoke);
        }

        System.out.println("调用完成，返回结果："+result.toString());

        channelHandlerContext.writeAndFlush(new MessageContext(String.valueOf(new Random().nextInt(9999)),true,new Response(true,result,returnType)));
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        System.out.println("发生了异常");
        cause.printStackTrace();
        ctx.close();
    }


}

